home *** CD-ROM | disk | FTP | other *** search
/ Nebula 1 / Nebula One.iso / Mail / pine3.92 / pico / ibmpc.c < prev    next >
C/C++ Source or Header  |  1996-03-14  |  14KB  |  676 lines

  1. /*
  2.  *
  3.  * $Id: ibmpc.c,v 4.12 1996/03/15 07:41:11 hubert Exp $
  4.  *
  5.  * Program:    IBM PC specific routine
  6.  *
  7.  *
  8.  * Michael Seibel
  9.  * Networks and Distributed Computing
  10.  * Computing and Communications
  11.  * University of Washington
  12.  * Administration Builiding, AG-44
  13.  * Seattle, Washington, 98195, USA
  14.  * Internet: mikes@cac.washington.edu
  15.  *
  16.  * Please address all bugs and comments to "pine-bugs@cac.washington.edu"
  17.  *
  18.  *
  19.  * Pine and Pico are registered trademarks of the University of Washington.
  20.  * No commercial use of these trademarks may be made without prior written
  21.  * permission of the University of Washington.
  22.  * 
  23.  * Pine, Pico, and Pilot software and its included text are Copyright
  24.  * 1989-1996 by the University of Washington.
  25.  * 
  26.  * The full text of our legal notices is contained in the file called
  27.  * CPYRIGHT, included with this distribution.
  28.  *
  29.  */
  30.  
  31. /*
  32.  * The routines in this file provide support for the IBM-PC and other
  33.  * compatible terminals. It goes directly to the graphics RAM to do
  34.  * screen output. It compiles into nothing if not an IBM-PC driver
  35.  */
  36.  
  37. #include        <stdio.h>
  38. #include    <conio.h>
  39. #include    <time.h>
  40. #include    "osdep.h"
  41. #if     IBMPC
  42. #define    termdef    1            /* don't define "term" external */
  43. #include    "pico.h"
  44. #include    "estruct.h"
  45. #include        "efunc.h"
  46. #include        "edef.h"
  47.  
  48. #ifdef    ANSI
  49.     int  ibmmove(int, int);
  50.     int  ibmeeol(void);
  51.     int  ibmputc(int);
  52.     int  ibmoutc(char);
  53.     int  ibmeeop(void);
  54.     int  ibmrev(int);
  55.     void beep(unsigned int, unsigned int);
  56.     int  cutebeep(void);
  57.     int  ibmbeep(void);
  58.     int  ibmopen(void);
  59.     int  ibmclose(void);
  60. #else
  61.     int  ibmmove();
  62.     int  ibmeeol();
  63.     int  ibmputc();
  64.     int  ibmoutc();
  65.     int  ibmeeop();
  66.     int  ibmrev();
  67.     void beep();
  68.     int  cutebeep();
  69.     int  ibmbeep();
  70.     int  ibmopen();
  71.     int  ibmclose();
  72. #endif
  73.  
  74.  
  75. #define NROW    25              /* Screen size.                 */
  76. #define NCOL    80              /* Edit if you want to.         */
  77. #define    MARGIN    8        /* size of minimim margin and    */
  78. #define    SCRSIZ    64        /* scroll size for extended lines */
  79. #define    MROW    2        /* rows in menu                 */
  80. #define    NPAUSE    200        /* # times thru update to pause */
  81. #define BEL     0x07            /* BEL character.               */
  82. #define ESC     0x1B            /* ESC character.               */
  83. #define    SPACE    32        /* space character        */
  84.  
  85.  
  86.  
  87.  
  88. #define     SET_COLOR(fore,back)    ((((back) & 0xf) << 4) | ((fore) & 0xf))
  89.  
  90. int     nfcolor = 7;        /* current forground color */
  91. int     nbcolor = 1;        /* current background color */
  92. int     rfcolor = 0;        /* reverse forground color */
  93. int     rbcolor = 3;        /* reverse background color */
  94. unsigned cattr;            /* current combined attribute */
  95.  
  96. /*
  97.  * Standard terminal interface dispatch table. Most of the fields point into
  98.  * "termio" code.
  99.  */
  100. TERM    term    = {
  101.         NROW-1,
  102.         NCOL,
  103.     MARGIN,
  104.     SCRSIZ,
  105.     MROW,
  106.         ibmopen,
  107.         ibmclose,
  108.         ttgetc,
  109.     ibmputc,
  110.         ttflush,
  111.         ibmmove,
  112.         ibmeeol,
  113.         ibmeeop,
  114.         ibmbeep,
  115.     ibmrev
  116. };
  117.  
  118.  
  119. #ifdef DOS
  120. extern union REGS rg;
  121. static unsigned display_mode;    /*  */
  122. #endif
  123.  
  124.  
  125. static char *colist[] = {
  126.     "black",
  127.     "blue",
  128.     "green",
  129.     "cyan",
  130.     "red",
  131.     "magenta",
  132.     "yellow",
  133.     "white",
  134.         "BLACK",
  135.         "BLUE",
  136.         "GREEN",
  137.         "CYAN",
  138.         "RED",
  139.         "MAGENTA",
  140.         "YELLOW",
  141.         "WHITE" };
  142.  
  143. /*
  144.  * pico_setcolor - given the color name, return the color's value
  145.  */
  146. int
  147. setcolor(s)
  148. char *s;
  149. {
  150.     int i;
  151.  
  152.     for (i=0; i<16; i++)
  153.       if (!strcmp(colist[i],s))
  154.     return(i);
  155.  
  156.     return(7);
  157. }
  158.  
  159.  
  160. /*
  161.  * pico_XXcolor() - each function sets a particular attribute
  162.  */
  163. pico_nfcolor(s)
  164. char *s;
  165. {
  166.     nfcolor = setcolor(s);
  167. }
  168.  
  169. pico_nbcolor(s)
  170. char *s;
  171. {
  172.     nbcolor = setcolor(s);
  173. }
  174.  
  175. pico_rfcolor(s)
  176. char *s;
  177. {
  178.     rfcolor = setcolor(s);
  179. }
  180.  
  181. pico_rbcolor(s)
  182. char *s;
  183. {
  184.     rbcolor = setcolor(s);
  185. }
  186.  
  187. #ifdef OS2
  188. static VIOMODEINFO display_mode;
  189. static BYTE *oldscreen =NULL;
  190. static USHORT origRow, origCol;
  191. static USHORT origLen =0;
  192. #ifdef FASTVIO
  193. extern HMOU Mouse_Handle;
  194. extern int mouse_state;
  195. static int was_mouse_state=-1;
  196. static int _moved=0, _line=0, _col=0;
  197. static USHORT usVidbufLength =0;
  198. static USHORT usRows =0, usCols =0;
  199. static USHORT * pusVidBuffer =NULL;
  200. static USHORT fCell=(USHORT)-1,
  201.               lCell=(USHORT)-1;
  202.  
  203. static HEV  hvUpdate =(HEV)0;
  204. static HMTX hxUpdate =(HMTX)0;
  205. static TID threadID;
  206. static NOPTRRECT noptr = { 0, 0, (USHORT)-1, (USHORT)-1 };
  207.  
  208. static void update_thread(ULONG args)
  209. {
  210.   while (DosWaitEventSem(hvUpdate, -1)==0) {
  211.     DosResetEventSem(hvUpdate, &args);
  212.     if (fCell!=(USHORT)-1) {
  213.       DosRequestMutexSem(hxUpdate,-1);
  214.       if (was_mouse_state && Mouse_Handle!=(HMOU)-1)
  215.     MouRemovePtr(&noptr, Mouse_Handle);
  216.       /* Update the screen, if required */
  217.       VioShowBuf(fCell*2,(lCell-fCell+1)*2, 0);
  218.       fCell=lCell=(USHORT)-1;
  219.       DosReleaseMutexSem(hxUpdate);
  220.       if (mouse_state && Mouse_Handle!=(HMOU)-1)
  221.     MouDrawPtr(Mouse_Handle);
  222.     }
  223.     else if (mouse_state != was_mouse_state && Mouse_Handle!=(HMOU)-1) {
  224.       if (mouse_state)
  225.     MouDrawPtr(Mouse_Handle);
  226.       else
  227.     MouRemovePtr(&noptr, Mouse_Handle);
  228.     }
  229.     was_mouse_state=mouse_state;
  230.     if (_moved) {
  231.       _moved=0;
  232.       VioSetCurPos((USHORT)_line,(USHORT)_col,0);
  233.     }
  234.     DosSleep(1);
  235.   }
  236. }
  237.  
  238. static void vidCell(USHORT row, USHORT col)
  239. {
  240.   USHORT cell=(row*usCols)+col;
  241.  
  242.   DosRequestMutexSem(hxUpdate,-1);
  243.   /* Always update first cell */
  244.   if (fCell==(USHORT)-1)
  245.     fCell=lCell=cell;
  246.   else {
  247.     /* Otherwise stretch limits if necessary */
  248.     if (cell<fCell)
  249.       fCell=cell;
  250.     if (cell>lCell)
  251.       lCell=cell;
  252.   }
  253.   DosReleaseMutexSem(hxUpdate);
  254. }
  255.  
  256. /* These seek to do minimal screen update
  257.  * by keeping track of the first and last
  258.  * cells written to the video buffer
  259.  */
  260.  
  261. void vidUpdate()
  262. {
  263.   if (hvUpdate == (HEV)0) {
  264.     VIOMODEINFO mi;
  265.  
  266.     DosCreateEventSem(NULL, &hvUpdate, 0, FALSE);
  267.     DosCreateMutexSem(NULL, &hxUpdate, 0, FALSE);
  268.     DosCreateThread(&threadID,update_thread,0,0,8192);
  269.     mi.cb = sizeof mi;
  270.     VioGetMode(&mi, 0);
  271.     noptr.cRow = mi.row-1;
  272.     noptr.cCol = mi.col-1;
  273.   }
  274.   DosPostEventSem(hvUpdate);
  275. }
  276.  
  277. static void vidArea(USHORT frow, USHORT fcol, USHORT lrow, USHORT lcol)
  278. {
  279.   vidCell(frow,fcol);
  280.   vidCell(lrow,lcol);
  281. }
  282. #endif
  283. #endif
  284.  
  285.  
  286. /*
  287.  * ibmmove - Use BIOS video services, function 2h to set cursor postion
  288.  */
  289. ibmmove(row, col)
  290. int row, col;
  291. {
  292. #ifdef OS2
  293. #ifdef FASTVIO
  294.   if (_line!=row || _col!=col) {
  295.     _line=row;
  296.     _col=col;
  297.     _moved=1;
  298.   }
  299. #else
  300.   VioSetCurPos((USHORT)row, (USHORT)col, 0);
  301. #endif
  302. #else
  303.     rg.h.ah = 2;        /* set cursor position function code */
  304.     rg.h.bh = 0;        /* set screen page number */
  305.     rg.h.dl = col;
  306.     rg.h.dh = row;
  307.     int86(BIOS_VIDEO, &rg, &rg);
  308. #endif
  309. }
  310.  
  311.  
  312. /*
  313.  * ibmeeol - erase to the end of the line
  314.  */
  315. ibmeeol()
  316. {
  317. #ifdef OS2
  318.   USHORT row, col;
  319.   BYTE chattr[2];
  320.   chattr[0] = ' ';
  321.   chattr[1] = (BYTE)cattr;
  322.  
  323. #ifdef FASTVIO
  324.   row=(USHORT)_line;
  325.   col=(USHORT)_col;
  326.   vidCell(row,col);
  327.   vidCell(row,usCols-1);
  328.   row=(row*usCols)+col;
  329.   col=usCols-col;
  330.   while(col--)
  331.     pusVidBuffer[row++] = *(USHORT *)chattr;
  332. #else
  333.   /* find the current cursor position */
  334.   VioGetCurPos(&row, &col, 0);
  335.   VioWrtNCell(chattr, NCOL-col, row, col, 0);
  336. #endif
  337. #else
  338.     int col, row, page;
  339.  
  340.     /* find the current cursor position */
  341.     rg.h.ah = 3;        /* read cursor position function code */
  342.     int86(BIOS_VIDEO, &rg, &rg);
  343.     page = rg.h.bh;
  344.     col = rg.h.dl;        /* record current column */
  345.     row = rg.h.dh;        /* and row */
  346.  
  347.     rg.h.ah = 0x09;        /* write char to screen with new attrs */
  348.     rg.h.al = ' ';
  349.     rg.h.bl = cattr;
  350.     rg.h.bh = page;
  351.     rg.x.cx = NCOL-col;
  352.     int86(BIOS_VIDEO, &rg, &rg);
  353. #endif
  354. }
  355.  
  356.  
  357. /*
  358.  * ibmputc - put a character at the current position in the
  359.  *         current colors
  360.  */
  361. ibmputc(ch)
  362. int ch;
  363. {
  364. #ifdef OS2
  365.   USHORT row, col;
  366.  
  367.   /* first, get current position */
  368. #ifdef FASTVIO
  369.   row=(USHORT)_line;
  370.   col=(USHORT)_col;
  371. #else
  372.   VioGetCurPos(&row, &col, 0);
  373. #endif
  374.   if (ch == '\b') {
  375.     if (col > 0)
  376.       ibmmove(row, --col);
  377.   }
  378.   else {
  379.     BYTE chattr[2];
  380.     chattr[0]=(BYTE)ch;
  381.     chattr[1]=(BYTE)cattr;
  382. #if FASTVIO
  383.     vidCell(row,col);
  384.     pusVidBuffer[(row*usCols)+col] = *(USHORT *)chattr;
  385.     if (col < usCols)
  386. #else
  387.       VioWrtNCell(chattr, 1, row, col, 0);
  388.     if (col < NCOL)
  389. #endif
  390.       ibmmove(row, ++col);
  391.   }
  392. #else
  393.     int col, row, page;
  394.  
  395.     rg.h.ah = 0x03;            /* first, get current position */
  396.     int86(BIOS_VIDEO, &rg, &rg);
  397.     page = rg.h.bh;
  398.     row = rg.h.dh;
  399.     col = rg.h.dl;
  400.     
  401.     if(ch == '\b'){
  402.     if(col > 0)        /* advance the cursor */
  403.       ibmmove(row, --col);
  404.     }
  405.     else{
  406.     rg.h.ah = 0x09;        /* write char to screen with new attrs */
  407.     rg.h.al = ch;
  408.     rg.h.bl = cattr;        /* inverting if needed */
  409.     rg.h.bh = page;
  410.     rg.x.cx = 1;        /* only once */
  411.     int86(BIOS_VIDEO, &rg, &rg);
  412.  
  413.     if(col < 80)        /* advance the cursor */
  414.       ibmmove(row, ++col);
  415.     }
  416. #endif
  417. }
  418.  
  419.  
  420. /* 
  421.  * ibmgetc - output a single character with the right attributes, but
  422.  *           don't advance the cursor
  423.  */
  424. ibmgetc(c)
  425. char *c;
  426. {
  427. #ifdef OS2
  428.   /* first, get current position */
  429. #if FASTVIO
  430.   *c=(BYTE)pusVidBuffer[(_line*usCols)+_col];
  431. #else
  432.   USHORT row, col, n = 1;
  433.  
  434.   VioGetCurPos(&row, &col, 0);
  435.   VioReadCharStr(c, 1, &n, row, col, 0);
  436. #endif
  437. #else
  438.     rg.h.ah = 8;            /* vid services, read char at cursor */
  439.     rg.h.bh = 0;
  440.     int86(0x10, &rg, &rg);
  441.     *c = rg.h.al;
  442. #endif
  443. }
  444.  
  445.  
  446. /*
  447.  * ibmeeop - clear from cursor to end of page
  448.  */
  449. ibmeeop()
  450. {
  451. #ifdef OS2
  452. #if FASTVIO
  453.   USHORT atofs;
  454. #endif
  455.   BYTE chattr[2];
  456.   chattr[0] = ' ';
  457.   chattr[1] = (BYTE)cattr;
  458.  
  459. #ifdef FASTVIO
  460.   vidArea(0,0,usRows-1,usCols-1);
  461.   for (atofs=0; atofs < usVidbufLength;++atofs)
  462.     pusVidBuffer[atofs] = *(USHORT *)chattr;
  463. #else
  464.   VioScrollUp(0, 0, -1, -1, -1, chattr, 0);
  465. #endif
  466. #else
  467.     rg.h.ah = 6;        /* scroll page up function code */
  468.     rg.h.al = 0;        /* # lines to scroll (clear it) */
  469.     rg.x.cx = 0;        /* upper left corner of scroll */
  470.     rg.x.dx = (term.t_nrow << 8) | (term.t_ncol - 1);
  471.     rg.h.bh = cattr;
  472.     int86(BIOS_VIDEO, &rg, &rg);
  473. #endif
  474.     ibmmove(0, 0);
  475. }
  476.  
  477.  
  478. /*
  479.  * ibmrev - change reverse video state
  480.  */
  481. ibmrev(state)
  482. int state;
  483. {
  484.     cattr = (state) ? SET_COLOR(rfcolor, rbcolor)
  485.             : SET_COLOR(nfcolor, nbcolor);
  486. }
  487.  
  488.  
  489. /*
  490.  * getrevstate - return the current reverse state
  491.  */
  492. getrevstate()
  493. {
  494.     return(cattr == SET_COLOR(rfcolor, rbcolor));
  495. }
  496.  
  497.  
  498. /* 
  499.  * beep - make the speaker sing!
  500.  */
  501. void
  502. beep(freq, dur)
  503. unsigned freq, dur;
  504. {
  505. #ifdef OS2
  506.   if (freq)
  507.     DosBeep(freq, dur);
  508. #else
  509.     unsigned oport;
  510.  
  511.     if(!freq)
  512.     return;
  513.  
  514.     freq = (unsigned)(1193180 / freq);
  515.     /* set up the timer */
  516.     outp(0x43, 0xb6);            /* set timer channel 2 registers */
  517.     outp(0x42, (0xff&freq));        /* low order byte of count */
  518.     outp(0x42, (freq>>8));        /* hi order byte of count */
  519.  
  520.     /* make the sound */
  521.     oport = inp(0x61);
  522.     outp(0x61, oport | 0x03);
  523.     ssleep((clock_t)((dur < 75) ? 75 : dur));
  524.     outp(0x61, oport);
  525. #endif
  526. }
  527.  
  528.  
  529. /*
  530.  * cutebeep - make the speeker sing the way we want!
  531.  */
  532. cutebeep()
  533. {
  534.     beep(575, 50);
  535. #ifndef OS2
  536.     ssleep((clock_t)25);
  537. #endif
  538.     beep(485, 90);
  539. }
  540.  
  541.  
  542. /*
  543.  * ibmbeep - system beep...
  544.  */
  545. ibmbeep()
  546. {
  547.     cutebeep();
  548. }
  549.  
  550.  
  551. /*
  552.  * enter_text_mode - get current video mode, saving to be restored 
  553.  *                   later, then explicitly set 80 col text mode.
  554.  *
  555.  *     NOTE: this gets kind of weird.  Both pine and pico call this
  556.  *           during initialization.  To make sure it's only invoked once
  557.  *           it only responds if passed NULL which pico only does if not
  558.  *           called from in pine, and pine does all the time.  make sense?
  559.  *           thought not.
  560.  */
  561. void
  562. enter_text_mode(p)
  563. PICO *p;
  564. {
  565. #ifdef OS2
  566.     if (!p) {
  567. #ifdef FASTVIO
  568.     ULONG pBuf;
  569. #endif
  570.     display_mode.cb = sizeof display_mode;
  571.     VioGetMode(&display_mode, 0);
  572.     term.t_ncol = display_mode.col;
  573.     term.t_nrow = display_mode.row - 1;
  574.     origLen = display_mode.row * display_mode.col * sizeof(USHORT);
  575.     if (oldscreen)
  576.       free(oldscreen);
  577.     oldscreen = malloc(origLen);
  578.     if (oldscreen)
  579.       VioReadCellStr(oldscreen, &origLen, 0, 0, 0);
  580.     VioGetCurPos(&origRow, &origCol, 0);
  581. #ifdef FASTVIO
  582.     _line=origRow;
  583.     _col=origCol;
  584. #endif
  585. #ifdef FASTVIO
  586.     usRows = display_mode.row;
  587.     usCols = display_mode.col;
  588.     VioGetBuf(&pBuf,&usVidbufLength,0);
  589.     pusVidBuffer = _emx_16to32((_far16ptr)pBuf);
  590.     /* OS2 2.1+ VIO bug (viobuf not initialised) workaround */
  591.     memcpy(pusVidBuffer,oldscreen,usVidbufLength);
  592.     usVidbufLength /= 2;  /* Cells, not bytes */
  593. #endif
  594.     }
  595. #else
  596.     static int i = 0;
  597.     if(!p && !i++){
  598.     rg.h.ah = 0x0f;            /* save old mode */
  599.     int86(BIOS_VIDEO, &rg, &rg);
  600.     display_mode = rg.h.al;
  601.  
  602.     rg.h.ah = 0;            /* then set text mode */
  603.     rg.h.al = 2;
  604.     int86(BIOS_VIDEO, &rg, &rg);        /* video services */
  605.     }
  606. #endif
  607. }
  608.  
  609.  
  610. /*
  611.  * exit_text_mode - leave text mode by restoring saved original 
  612.  *                  video mode.
  613.  */
  614. void
  615. exit_text_mode(p)
  616. PICO *p;
  617. {
  618.  
  619. #ifdef OS2
  620.     if (!p) {
  621.         turnmouseoff(); /* Make sure mouse is off while display is updated */
  622.     VioSetMode(&display_mode, 0);
  623.     if (!oldscreen)
  624.     {
  625.       ibmeeop();
  626.       VioSetCurPos(display_mode.row-1, 0, 0);
  627.     }
  628.     else
  629.     {
  630.       VioWrtCellStr(oldscreen, origLen, 0, 0, 0);
  631.       VioSetCurPos(origRow, origCol, 0);
  632.     }
  633.     }
  634. #else
  635.     static int i = 0;
  636.     if(!p && !i++){            /* called many, invoke once! */
  637.     rg.h.ah = 0;            /* just restore old mode */
  638.     rg.h.al = display_mode;
  639.     int86(BIOS_VIDEO, &rg, &rg);
  640.     }
  641. #endif
  642. }
  643.  
  644.  
  645. /*
  646.  * ibmopen - setup text mode and setup key labels...
  647.  */
  648. ibmopen()
  649. {
  650.  
  651.     enter_text_mode(Pmaster);
  652.  
  653.     cattr    = SET_COLOR(nfcolor, nbcolor);
  654.     revexist = TRUE;
  655.     inschar  = delchar = 0;
  656.  
  657.     ttopen();
  658. }
  659.  
  660.  
  661. ibmclose()
  662. {
  663. #if    COLOR
  664.     ibmfcol(7);
  665.     ibmbcol(0);
  666. #endif
  667. #ifdef MOUSE
  668.     mouseoff();
  669. #endif
  670.     exit_text_mode(Pmaster);
  671.  
  672.     ttclose();
  673. }
  674. #endif
  675.  
  676.